home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / CH_4.4 / XPM / XPM.C < prev    next >
C/C++ Source or Header  |  1999-09-11  |  7KB  |  308 lines

  1. /* 
  2.  * xpm.c
  3.  * 
  4.  * Practical Algorithms for Image Analysis
  5.  * 
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /*
  10.  * XP(olygon)M(oments)
  11.  *
  12.  * extracts global features and performs a moment analysis
  13.  * on planar boundaries
  14.  *
  15.  */
  16. #include "xpm.h"
  17.  
  18.  
  19. #define    WINDOW_ROWS    3
  20. #define NDIRECTIONS    8
  21.  
  22. #define    THRESH        1
  23. #define MIN_POLY_SIZE    20
  24. #define    ZERO        0
  25. #define ROOT2        1.414213562
  26.  
  27. #define    NA_MAX        128             /* lim of points, see ph.c */
  28.  
  29. #define    ON        1
  30. #define    OFF        0
  31.  
  32. #define    RESET        ON
  33. #define NO_RESET    OFF
  34.  
  35. #undef    DEBUG
  36. #undef    SHOW_CURV_PT
  37.  
  38.  
  39. /* global variables */
  40. extern short tiffInput;         /* flag=0 if no ImageIn to set tags; else =1 */
  41. struct curv_points *curv_head_in[NDIRECTIONS];
  42. struct curv_points *curv_head_out[NDIRECTIONS];
  43. struct curv_points *curv_tail_in[NDIRECTIONS];
  44. struct curv_points *curv_tail_out[NDIRECTIONS];
  45.  
  46. struct polygon *poly_head_ptr;
  47. struct polygon *poly_tail_ptr;
  48. float *delta_phik, *delta_lk;
  49.  
  50. long ncp = 0;
  51.  
  52. int loop_switch = ON;           /* enable/disable loop for polyg. approx */
  53. int hull_switch = ON;           /* enable/disable eval of convex hull */
  54. int n_ap_max = NA_MAX;          /* max no allowed vertices in approx. poly */
  55.  
  56. extern char *optarg;
  57. extern int optind, opterr;
  58. extern short tiffInput;         /* flag=0 if no ImageIn to set tags; else =1 */
  59.  
  60. /*
  61.  * usage of routine
  62.  */
  63. void
  64. usage (char *progname)
  65. {
  66.   progname = last_bs (progname);
  67.   printf ("USAGE: %s inimg outimg [-L]\n", progname);
  68.   printf ("\n%s extracts global features and performs a moment analysis\n", progname);
  69.   printf ("on planar boundaries\n\n");
  70.   printf ("ARGUMENTS:\n");
  71.   printf ("       inimg: input image filename (TIF)\n");
  72.   printf ("      outimg: output image filename (TIF)\n\n");
  73.   printf ("OPTIONS:\n");
  74.   printf ("          -L: print Software License for this module\n");
  75.  
  76.   exit (1);
  77. }
  78.  
  79. void
  80. init_structs ()
  81. {
  82.   int m;
  83.  
  84.   for (m = 0; m < NDIRECTIONS; m++) {
  85.     curv_tail_in[m] = curv_tail_out[m] = NULL;
  86.     curv_head_in[m] = curv_head_out[m] = NULL;
  87.   }
  88.   poly_head_ptr = NULL;
  89.   poly_tail_ptr = NULL;
  90. }
  91.  
  92. /*
  93.  * acquire first three rows from input image
  94.  * and transfer them to the window
  95.  */
  96. void
  97. xfer_first_3_rows (unsigned char *window[], Image * imgIO)
  98. {
  99.   int ir;
  100.  
  101.   for (ir = 0; ir < 3; ir++)
  102.     getrow (*(window + ir), ir, imgIO);
  103. }
  104.  
  105. /*
  106.  * acquire next from input image
  107.  * and transfer it to the window
  108.  */
  109. void
  110. xfer_next_row (unsigned char *window[], int ir, Image * imgIO)
  111. {
  112.   int y;
  113.   unsigned char *char_ptr;
  114.  
  115.   char_ptr = *(window + (ir % WINDOW_ROWS));
  116.   y = ir + 3;                   /* offset of 3 from first_3_rows */
  117.   getrow (char_ptr, y, imgIO);
  118. }
  119.  
  120. /*
  121.  * zero border error message
  122.  */
  123. void
  124. border_err (int row, int col)
  125. {
  126.   printf ("...AOI border not zeroed at row %d, col %d\n", row, col);
  127.   exit (1);
  128. }
  129.  
  130. /*
  131.  * image border must be zeroed -- check it!
  132.  */
  133. void
  134. check_border (unsigned char *window[], int ir, int jmax, int imax, Image * imgIO)
  135. {
  136.   int jc;
  137.   unsigned char *char_ptr;
  138.  
  139.   if (ir == 0) {
  140.     char_ptr = *(window + (ir % WINDOW_ROWS));
  141.     for (jc = 0; jc < jmax; jc++)
  142.       if (*(char_ptr + jc) != ZERO)
  143.         border_err (ir, jc);
  144.   }
  145.   if (ir == (imax - WINDOW_ROWS)) {
  146.     char_ptr = *(window + ((ir + 0) % WINDOW_ROWS));
  147.     if (*(char_ptr) != ZERO)
  148.       border_err (ir, 0);
  149.     if (*(char_ptr + (jmax - 1)) != ZERO)
  150.       border_err (ir, jmax - 1);
  151.  
  152.     char_ptr = *(window + ((ir + 1) % WINDOW_ROWS));
  153.     if (*(char_ptr) != ZERO)
  154.       border_err (ir + 1, 0);
  155.     if (*(char_ptr + (jmax - 1)) != ZERO)
  156.       border_err (ir + 1, jmax - 1);
  157.  
  158.     char_ptr = *(window + ((ir + 2) % WINDOW_ROWS));
  159.     for (jc = 0; jc < jmax; jc++)
  160.       if (*(char_ptr + jc) != ZERO)
  161.         border_err (ir + 2, jc);
  162.   }
  163.   else {
  164.     char_ptr = *(window + (ir % WINDOW_ROWS));
  165.     if (*(char_ptr) != ZERO)
  166.       border_err (ir, 0);
  167.     if (*(char_ptr + (jmax - 1)) != ZERO)
  168.       border_err (ir, jmax - 1);
  169.   }
  170. }
  171.  
  172. /*
  173.  * memory allocation for image (one row at a time)
  174.  */
  175. int
  176. img_alloc (unsigned char *img[], int nr, int nc)
  177. {
  178.   int ir;
  179.  
  180.   for (ir = 0; ir < nr; ir++) {
  181.     if ((*(img + ir) = (unsigned char *) calloc (nc, sizeof (unsigned char))) == NULL)
  182.         return (0);
  183.     else
  184.       *(img + ir) += 0;
  185.  
  186.   }
  187.   return (1);
  188. }
  189.  
  190.  
  191. void
  192. main (int argc, char *argv[])
  193. {
  194.   unsigned char *window[WINDOW_ROWS];
  195.   int ir;
  196.   int nr, nc;
  197.   int jmin, imin, jmax, imax;
  198.   int left_x, right_x;
  199.   float *delta_phikp, *delta_lkp;
  200.   Image *imgIn;                 /* input image */
  201.   Image *imgOut;                /* output image */
  202.   int i_arg;
  203.  
  204. /*
  205.  * cmd line options
  206.  */
  207.   static char *optstring = "c:bL";
  208.  
  209.  
  210. /*
  211.  * parse command line
  212.  */
  213.   optind = 3;                   /* set getopt to point to the 3rd arg */
  214.   opterr = ON;                  /* give error messages */
  215.  
  216.  
  217.   if (argc < 3)
  218.     usage (argv[0]);
  219.  
  220.   while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
  221.     switch (i_arg) {
  222.     case 'L':
  223.       print_sos_lic ();
  224.       exit (0);
  225.     default:
  226.       printf ("\ngetopt: unknown condition encountered\n");
  227.       exit (1);
  228.       break;
  229.     }
  230.   }
  231. /*
  232.  * initialize structures
  233.  */
  234.   init_structs ();
  235.  
  236. /*
  237.  * get the input image
  238.  */
  239.   imgIn = ImageIn (argv[1]);
  240.   if (imgIn->bps == 8 && imgIn->spp == 3) {
  241.     printf ("Got RGB image!!!\n");
  242.     fprintf (stderr, "Can only work with Grayscale or Binary TIFF files!!!\n");
  243.     exit (1);
  244.   }
  245.  
  246.   /* reset tiffInput so that we write a grayscale file (i.e tags are not copied) */
  247.   tiffInput = 0;
  248. /*
  249.  * initialize for output image (Grayscale!!)
  250.  */
  251.   imgOut = ImageAlloc (imgIn->height, imgIn->width, 8);
  252.  
  253.   jmin = imin = 0;
  254.   jmax = imgIn->width;
  255.   imax = imgIn->height;
  256.  
  257.   left_x = jmin;
  258.   right_x = jmax - 1;
  259.   nc = jmax - jmin;
  260.   nr = imax - imin;
  261.  
  262. #ifdef DEBUG
  263.   printf ("\n...nc = %d, nr = %d\n", nc, nr);
  264. #endif
  265.  
  266. /*
  267.  *  zero outer border of image
  268.  */
  269.   zero_border (imgIn, 2);
  270.  
  271. /*
  272.  * allocate memory
  273.  */
  274.   if ((img_alloc (window, WINDOW_ROWS, nc) == 0))
  275.     exitmess ("window", 1);
  276.  
  277.   printf ("\n...scan image...\n");
  278.   xfer_first_3_rows (window, imgIn);
  279.   for (ir = 0; ir < imax - WINDOW_ROWS; ir++) {
  280.     check_border (window, ir, jmax, imax, imgIn);
  281.     curvature_points (window, ir, jmax, imax);
  282.     xfer_next_row (window, ir, imgIn);
  283.   }
  284.   check_border (window, ir, jmax, imax, imgIn);
  285.   curvature_points (window, ir, jmax, imax);
  286.  
  287.  
  288.   if ((delta_phikp = (float *) calloc (ncp, sizeof (float))) == NULL)
  289.       exitmess ("delta_phik", 1);
  290.   if ((delta_lkp = (float *) calloc (ncp, sizeof (float))) == NULL)
  291.       exitmess ("delta_phik", 1);
  292.   delta_phik = delta_phikp;
  293.   delta_lk = delta_lkp;
  294.  
  295. /*
  296.  * construct lists representing individual boundaries
  297.  */
  298.   printf ("...construct linked lists of boundary points...\n");
  299.   linkage (imgIn, imgOut, WHITE);
  300.  
  301.  
  302.  
  303.   free (delta_phikp);
  304.   free (delta_lkp);
  305.   printf ("\n...writing graphics output file %s\n", argv[2]);
  306.   ImageOut (argv[2], imgOut);
  307. }
  308.